#include "TaskExecutor.h"
#include <functional>

namespace toolkit {

TaskExecutorImp::TaskExecutorImp(size_t thread_num) : _thread_num(thread_num) {
    // 创建线程池
    for (size_t i = 0; i < thread_num; ++i) {
        _threads.emplace_back([this]() { run(); });
    }
}

TaskExecutorImp::~TaskExecutorImp() {
    _exit_flag = true;
    // 通知所有线程退出
    _task_queue.push_exit(_thread_num);
    // 等待所有线程结束
    for (auto &thread : _threads) {
        if (thread.joinable()) {
            thread.join();
        }
    }
}

TaskCancelable::Ptr TaskExecutorImp::async(Task task, bool may_sync) {
    if (may_sync && _thread_num == 0) {
        // 同步执行
        task();
        return nullptr;
    }

    auto cancelable = std::make_shared<TaskCancelableImp>();
    auto wrapped_task = [cancelable, task]() {
        if (!cancelable->isCanceled()) {
            task();
        }
    };

    _task_queue.push_task(std::move(wrapped_task));
    return cancelable;
}

TaskCancelable::Ptr TaskExecutorImp::async_first(Task task, bool may_sync) {
    if (may_sync && _thread_num == 0) {
        // 同步执行
        task();
        return nullptr;
    }

    auto cancelable = std::make_shared<TaskCancelableImp>();
    auto wrapped_task = [cancelable, task]() {
        if (!cancelable->isCanceled()) {
            task();
        }
    };

    _task_queue.push_task_first(std::move(wrapped_task));
    return cancelable;
}

int TaskExecutorImp::getLoad() {
    return _thread_load.getLoad();
}

void TaskExecutorImp::run() {
    Task task;
    while (!_exit_flag) {
        // 获取任务
        if (!_task_queue.get_task(task)) {
            // 队列为空但信号量被触发，可能是退出信号
            continue;
        }

        // 执行任务
        _thread_load.addLoad();
        try {
            task();
        } catch (std::exception &e) {
            // 处理任务执行异常
        } catch (...) {
            // 处理未知异常
        }
        _thread_load.reduceLoad();
    }
}

TaskExecutorGetterImp::TaskExecutorGetterImp(const TaskExecutor::Ptr &executor) : _executor(executor) {
}

TaskExecutor::Ptr TaskExecutorGetterImp::getExecutor() {
    return _executor;
}

} /* namespace toolkit */